#pragma once
#include "feDefs.h"
#include "feMesh.h"
#include "feSmartPtr.h"

class feMesh;
struct fePoint;
class feVector;
class feDenseMatrix;
class feMaterial;

class feElement
{
protected:
	feMesh				*Mesh;
	feSharedPtr<feMaterial> Material;

public:
	virtual fePoint		NodeCoords(int iLocalN) { return Mesh->GetNode(NodeIndex(iLocalN)); }
	virtual	void		SetMesh(feMesh *iMesh)  { Mesh = iMesh; }
	virtual int			NodeIndex(int iLocalN) = 0;
	virtual void		GetStiffness(feDenseMatrix **oMatrix) = 0;
	virtual void		GetWeight(feDenseMatrix **oMatrix) = 0;
	virtual void		GetRight(feVector *oVector, int iLayer) = 0;
	virtual void		GetIndeces(int *oIndeces) = 0;
	virtual feMaterial*	GetMaterial() { return Material; }
};


//-----------------------------------------------------------------------------------------------------------------------------
class feQuadraticElement1d : public feElement
{
	int StartNode;	
	int Lookup1;
	int Lookup2;
	int Lookup3;

	double StiffRightCoeff;
	double WeightRightCoeff;

public:
	feQuadraticElement1d() { StartNode = 0; Lookup1 = 0; Lookup2 = 0; Lookup3 = 0;}
	feQuadraticElement1d(int iStartNode, feMesh* iMesh, feSharedPtr<feMaterial> iMat);
	feQuadraticElement1d(feQuadraticElement1d &iEl, int iStartNode) { Lookup1 = -1; Lookup2 = -1 ;Lookup3 = -1; Mesh = iEl.Mesh; Material = iEl.Material; StartNode = iStartNode; }
	
	void	SetStartNode(int iStartNode) { StartNode = iStartNode;}
	virtual fePoint	NodeCoords(int iLocalN);
	virtual int		NodeIndex(int iLocalN);
	virtual void	GetStiffness(feDenseMatrix **oMatrix);
	virtual void	GetWeight(feDenseMatrix **oMatrix);
	virtual void	GetRight(feVector *oVecto, int iLayer);
	virtual void	GetIndeces(int *oIndeces);
	void	SetRightCoeff(double iStiff=0, double iWeight=1) { StiffRightCoeff = iStiff; WeightRightCoeff = iWeight; }
};


//-----------------------------------------------------------------------------------------------------------------------------
class feLinearElement1d : public feElement
{
	int StartNode;	
	int Lookup1;
	int Lookup2;

	static double StiffRightCoeff;
	static double WeightRightCoeff;

public:
	feLinearElement1d() { StartNode = 0; Lookup1 = 0; Lookup2 = 0; }
	feLinearElement1d(int iStartNode, feMesh* iMesh, feSharedPtr<feMaterial> iMat);
	feLinearElement1d(feLinearElement1d &iEl, int iStartNode) { 	Lookup1 = -1; Lookup2 = -1; Mesh = iEl.Mesh; Material = iEl.Material; 
																			StartNode = iStartNode; }

	void	SetStartNode(int iStartNode) { StartNode = iStartNode;}
	virtual fePoint	NodeCoords(int iLocalN);
	virtual int		NodeIndex(int iLocalN);
	virtual void	GetStiffness(feDenseMatrix **oMatrix);
	virtual void	GetWeight(feDenseMatrix **oMatrix);
	virtual void	GetRight(feVector *oVector, int iLayer);
	virtual void	GetIndeces(int *oIndeces);
	static	void	SetRightCoeff(double iStiff=0, double iWeight=1) { feLinearElement1d::StiffRightCoeff = iStiff; feLinearElement1d::WeightRightCoeff = iWeight; }
};